home *** CD-ROM | disk | FTP | other *** search
/ IRIX Patches 1995 June / SGI IRIX Patches 1995 Jun.iso / 5.3_patches / patchSG0000154 / patchSG0000154.idb / usr / share / src / OpenGL / exts / surfgrid.c.z / surfgrid.c
Encoding:
C/C++ Source or Header  |  1995-06-12  |  23.5 KB  |  760 lines

  1. /*
  2.  * surfgrid.c - simple test of polygon offset
  3.  *
  4.  *  $Revision: 1.4 $
  5.  *
  6.  * usage:
  7.  *    surfgrid [-f]
  8.  *
  9.  * options:
  10.  *    -f    run on full screen
  11.  *
  12.  * keys:
  13.  *    p    toggle polygon offset
  14.  *    m    toggle multisampling
  15.  *      S       increase polygon offset factor
  16.  *      s       decrease polygon offset factor
  17.  *      B       increase polygon offset bias
  18.  *      b       decrease polygon offset bias
  19.  *    g    toggle grid drawing
  20.  *    f    toggle smooth/flat shading
  21.  *    n    toggle whether to use GL evaluators or GLU nurbs
  22.  *    u    decr number of segments in U direction
  23.  *    U    incr number of segments in U direction
  24.  *    v    decr number of segments in V direction
  25.  *    V    incr number of segments in V direction
  26.  *    escape    quit
  27.  */
  28. #include <stdio.h>
  29. #include <string.h>
  30. #include <stdlib.h>
  31. #include <math.h>
  32. #include <GL/gl.h>
  33. #include <GL/glx.h>
  34. #include <GL/glu.h>
  35. #include <X11/keysym.h>
  36. #include <Xm/MwmUtil.h>
  37.  
  38. #define W 600
  39. #define H 600
  40.  
  41.  
  42. static GLfloat controlpts[] = {
  43.      4.0, 0.0, 0.0, 4.0, 2.0, 0.0, 1.0, 2.0, 3.0, 0.0, 1.0, 2.0,
  44.          3.0, 0.0, 1.0, 2.0, 4.0, 0.0, 1.0, 2.0, 8.0, 0.0, 0.0, 4.0,
  45.          8.0, 0.0, 0.0, 4.0, 4.0, 0.0,-1.0, 2.0, 3.0, 0.0,-1.0, 2.0,
  46.          3.0, 0.0,-1.0, 2.0, 2.0, 0.0,-1.0, 2.0, 4.0, 0.0, 0.0, 4.0,
  47.          2.0,-2.0, 0.0, 2.0, 1.0,-1.0, 0.5, 1.0, 1.5,-1.5, 0.5, 1.0,
  48.          1.5,-1.5, 0.5, 1.0, 2.0,-2.0, 0.5, 1.0, 4.0,-4.0, 0.0, 2.0,
  49.          4.0,-4.0, 0.0, 2.0, 2.0,-2.0,-0.5, 1.0, 1.5,-1.5,-0.5, 1.0,
  50.          1.5,-1.5,-0.5, 1.0, 1.0,-1.0,-0.5, 1.0, 2.0,-2.0, 0.0, 2.0,
  51.          0.0,-2.0, 0.0, 2.0, 0.0,-1.0, 0.5, 1.0, 0.0,-1.5, 0.5, 1.0,
  52.          0.0,-1.5, 0.5, 1.0, 0.0,-2.0, 0.5, 1.0, 0.0,-4.0, 0.0, 2.0,
  53.          0.0,-4.0, 0.0, 2.0, 0.0,-2.0,-0.5, 1.0, 0.0,-1.5,-0.5, 1.0,
  54.          0.0,-1.5,-0.5, 1.0, 0.0,-1.0,-0.5, 1.0, 0.0,-2.0, 0.0, 2.0,
  55.          0.0,-2.0, 0.0, 2.0, 0.0,-1.0, 0.5, 1.0, 0.0,-1.5, 0.5, 1.0,
  56.          0.0,-1.5, 0.5, 1.0, 0.0,-2.0, 0.5, 1.0, 0.0,-4.0, 0.0, 2.0,
  57.          0.0,-4.0, 0.0, 2.0, 0.0,-2.0,-0.5, 1.0, 0.0,-1.5,-0.5, 1.0,
  58.          0.0,-1.5,-0.5, 1.0, 0.0,-1.0,-0.5, 1.0, 0.0,-2.0, 0.0, 2.0,
  59.         -2.0,-2.0, 0.0, 2.0,-1.0,-1.0, 0.5, 1.0,-1.5,-1.5, 0.5, 1.0,
  60.         -1.5,-1.5, 0.5, 1.0,-2.0,-2.0, 0.5, 1.0,-4.0,-4.0, 0.0, 2.0,
  61.         -4.0,-4.0, 0.0, 2.0,-2.0,-2.0,-0.5, 1.0,-1.5,-1.5,-0.5, 1.0,
  62.         -1.5,-1.5,-0.5, 1.0,-1.0,-1.0,-0.5, 1.0,-2.0,-2.0, 0.0, 2.0,
  63.         -4.0, 0.0, 0.0, 4.0,-2.0, 0.0, 1.0, 2.0,-3.0, 0.0, 1.0, 2.0,
  64.         -3.0, 0.0, 1.0, 2.0,-4.0, 0.0, 1.0, 2.0,-8.0, 0.0, 0.0, 4.0,
  65.         -8.0, 0.0, 0.0, 4.0,-4.0, 0.0,-1.0, 2.0,-3.0, 0.0,-1.0, 2.0,
  66.         -3.0, 0.0,-1.0, 2.0,-2.0, 0.0,-1.0, 2.0,-4.0, 0.0, 0.0, 4.0,
  67.         -4.0, 0.0, 0.0, 4.0,-2.0, 0.0, 1.0, 2.0,-3.0, 0.0, 1.0, 2.0,
  68.         -3.0, 0.0, 1.0, 2.0,-4.0, 0.0, 1.0, 2.0,-8.0, 0.0, 0.0, 4.0,
  69.         -8.0, 0.0, 0.0, 4.0,-4.0, 0.0,-1.0, 2.0,-3.0, 0.0,-1.0, 2.0,
  70.         -3.0, 0.0,-1.0, 2.0,-2.0, 0.0,-1.0, 2.0,-4.0, 0.0, 0.0, 4.0,
  71.         -2.0, 2.0, 0.0, 2.0,-1.0, 1.0, 0.5, 1.0,-1.5, 1.5, 0.5, 1.0,
  72.         -1.5, 1.5, 0.5, 1.0,-2.0, 2.0, 0.5, 1.0,-4.0, 4.0, 0.0, 2.0,
  73.         -4.0, 4.0, 0.0, 2.0,-2.0, 2.0,-0.5, 1.0,-1.5, 1.5,-0.5, 1.0,
  74.         -1.5, 1.5,-0.5, 1.0,-1.0, 1.0,-0.5, 1.0,-2.0, 2.0, 0.0, 2.0,
  75.          0.0, 2.0, 0.0, 2.0, 0.0, 1.0, 0.5, 1.0, 0.0, 1.5, 0.5, 1.0,
  76.          0.0, 1.5, 0.5, 1.0, 0.0, 2.0, 0.5, 1.0, 0.0, 4.0, 0.0, 2.0,
  77.          0.0, 4.0, 0.0, 2.0, 0.0, 2.0,-0.5, 1.0, 0.0, 1.5,-0.5, 1.0,
  78.          0.0, 1.5,-0.5, 1.0, 0.0, 1.0,-0.5, 1.0, 0.0, 2.0, 0.0, 2.0,
  79.          0.0, 2.0, 0.0, 2.0, 0.0, 1.0, 0.5, 1.0, 0.0, 1.5, 0.5, 1.0,
  80.          0.0, 1.5, 0.5, 1.0, 0.0, 2.0, 0.5, 1.0, 0.0, 4.0, 0.0, 2.0,
  81.          0.0, 4.0, 0.0, 2.0, 0.0, 2.0,-0.5, 1.0, 0.0, 1.5,-0.5, 1.0,
  82.          0.0, 1.5,-0.5, 1.0, 0.0, 1.0,-0.5, 1.0, 0.0, 2.0, 0.0, 2.0,
  83.          2.0, 2.0, 0.0, 2.0, 1.0, 1.0, 0.5, 1.0, 1.5, 1.5, 0.5, 1.0,
  84.          1.5, 1.5, 0.5, 1.0, 2.0, 2.0, 0.5, 1.0, 4.0, 4.0, 0.0, 2.0,
  85.          4.0, 4.0, 0.0, 2.0, 2.0, 2.0,-0.5, 1.0, 1.5, 1.5,-0.5, 1.0,
  86.          1.5, 1.5,-0.5, 1.0, 1.0, 1.0,-0.5, 1.0, 2.0, 2.0, 0.0, 2.0,
  87.          4.0, 0.0, 0.0, 4.0, 2.0, 0.0, 1.0, 2.0, 3.0, 0.0, 1.0, 2.0,
  88.          3.0, 0.0, 1.0, 2.0, 4.0, 0.0, 1.0, 2.0, 8.0, 0.0, 0.0, 4.0,
  89.          8.0, 0.0, 0.0, 4.0, 4.0, 0.0,-1.0, 2.0, 3.0, 0.0,-1.0, 2.0,
  90.          3.0, 0.0,-1.0, 2.0, 2.0, 0.0,-1.0, 2.0, 4.0, 0.0, 0.0, 4.0,
  91. };
  92.  
  93.  
  94. static GLfloat nurbctlpts[] = {
  95.          4.0, 0.0, 0.0, 4.0, 2.0, 0.0, 1.0, 2.0, 4.0, 0.0, 1.0, 2.0,
  96.          8.0, 0.0, 0.0, 4.0, 4.0, 0.0,-1.0, 2.0, 2.0, 0.0,-1.0, 2.0,
  97.          4.0, 0.0, 0.0, 4.0, 2.0,-2.0, 0.0, 2.0, 1.0,-1.0, 0.5, 1.0,
  98.          2.0,-2.0, 0.5, 1.0, 4.0,-4.0, 0.0, 2.0, 2.0,-2.0,-0.5, 1.0,
  99.          1.0,-1.0,-0.5, 1.0, 2.0,-2.0, 0.0, 2.0,-2.0,-2.0, 0.0, 2.0,
  100.         -1.0,-1.0, 0.5, 1.0,-2.0,-2.0, 0.5, 1.0,-4.0,-4.0, 0.0, 2.0,
  101.         -2.0,-2.0,-0.5, 1.0,-1.0,-1.0,-0.5, 1.0,-2.0,-2.0, 0.0, 2.0,
  102.         -4.0, 0.0, 0.0, 4.0,-2.0, 0.0, 1.0, 2.0,-4.0, 0.0, 1.0, 2.0,
  103.         -8.0, 0.0, 0.0, 4.0,-4.0, 0.0,-1.0, 2.0,-2.0, 0.0,-1.0, 2.0,
  104.         -4.0, 0.0, 0.0, 4.0,-2.0, 2.0, 0.0, 2.0,-1.0, 1.0, 0.5, 1.0,
  105.         -2.0, 2.0, 0.5, 1.0,-4.0, 4.0, 0.0, 2.0,-2.0, 2.0,-0.5, 1.0,
  106.         -1.0, 1.0,-0.5, 1.0,-2.0, 2.0, 0.0, 2.0, 2.0, 2.0, 0.0, 2.0,
  107.          1.0, 1.0, 0.5, 1.0, 2.0, 2.0, 0.5, 1.0, 4.0, 4.0, 0.0, 2.0,
  108.          2.0, 2.0,-0.5, 1.0, 1.0, 1.0,-0.5, 1.0, 2.0, 2.0, 0.0, 2.0,
  109.          4.0, 0.0, 0.0, 4.0, 2.0, 0.0, 1.0, 2.0, 4.0, 0.0, 1.0, 2.0,
  110.          8.0, 0.0, 0.0, 4.0, 4.0, 0.0,-1.0, 2.0, 2.0, 0.0,-1.0, 2.0,
  111.          4.0, 0.0, 0.0, 4.0,
  112. };
  113.  
  114.  
  115. /*
  116.  * Misc vector op routines.
  117.  */
  118.  
  119. float x_axis[] = { 1.0, 0.0, 0.0 };
  120. float y_axis[] = { 0.0, 1.0, 0.0 };
  121. float z_axis[] = { 0.0, 0.0, 1.0 };
  122. float nx_axis[] = { -1.0, 0.0, 0.0 };
  123. float ny_axis[] = { 0.0, -1.0, 0.0 };
  124. float nz_axis[] = { 0.0, 0.0, -1.0 };
  125.  
  126. void norm(float v[3])
  127. {
  128.     float r;
  129.  
  130.     r = sqrt( v[0]*v[0] + v[1]*v[1] + v[2]*v[2] );
  131.  
  132.     v[0] /= r;
  133.     v[1] /= r;
  134.     v[2] /= r;
  135. }
  136.  
  137. float dot(float a[3], float b[3])
  138. {
  139.     return (a[0]*b[0] + a[1]*b[1] + a[2]*b[2]);
  140. }
  141.  
  142. void cross(float v1[3], float v2[3], float result[3])
  143. {
  144.     result[0] = v1[1]*v2[2] - v1[2]*v2[1];
  145.     result[1] = v1[2]*v2[0] - v1[0]*v2[2];
  146.     result[2] = v1[0]*v2[1] - v1[1]*v2[0];
  147. }
  148.  
  149. float length(float v[3])
  150. {
  151.     float r = sqrt( v[0]*v[0] + v[1]*v[1] + v[2]*v[2] );
  152.     return r;
  153. }
  154.  
  155.  
  156. static long winwidth = W, winheight = H;
  157. GC xgc;
  158. Display *dpy;
  159. Colormap cmap;
  160. Window window;
  161. XVisualInfo *vi;
  162. GLXContext cx;
  163. GLUnurbsObj *nobj;
  164. GLuint surflist, gridlist;
  165.  
  166. int useglunurbs = 0;
  167. int smooth = 1;
  168. int tracking = 0;
  169. int showgrid = 1;
  170. int showsurf = 1;
  171. int fullscreen = 0;
  172. int multisampling = 0;
  173. float modelmatrix[16];
  174. float scale = 0.5;
  175. float bias = 0.002;
  176. int usegments=4;
  177. int vsegments=4;
  178.  
  179. int spindx, spindy;
  180. int startx, starty;
  181. int curx, cury;
  182.  
  183. void redraw(void);
  184. void createlists(void);
  185.  
  186. float torusnurbpts[];
  187. float torusbezierpts[];
  188.  
  189. void eventloop( void )
  190. {
  191.     XEvent event;
  192.     XButtonEvent *bev;
  193.     int x, y, size;
  194.     unsigned int w, h, bw, depth;
  195.     Window root;
  196.     
  197.     for (;;) {
  198.     if (XPending(dpy)) {
  199.         XNextEvent(dpy, &event);
  200.         bev = (XButtonEvent *) &event;
  201.         switch (event.type) {
  202.           case KeyPress:
  203.         {
  204.             char buf[100];
  205.             int rv;
  206.             KeySym ks;
  207.  
  208.             rv = XLookupString(&event.xkey, buf, sizeof(buf), &ks, 0);
  209.             switch (ks) {
  210.               case XK_n:
  211.             useglunurbs = !useglunurbs;
  212.             break;
  213.               case XK_p:
  214.                         if (glIsEnabled( GL_POLYGON_OFFSET_EXT )) {
  215.                 glDisable( GL_POLYGON_OFFSET_EXT );
  216.                 printf("disabling polygon offset\n");
  217.             } else {
  218.                 glEnable( GL_POLYGON_OFFSET_EXT );
  219.                 printf("enabling polygon offset\n");
  220.             }
  221.             break;
  222.               case XK_m:
  223.             if (multisampling) {
  224.                 if (glIsEnabled( GL_MULTISAMPLE_SGIS )) {
  225.                 glDisable( GL_MULTISAMPLE_SGIS );
  226.                 } else {
  227.                 glEnable( GL_MULTISAMPLE_SGIS );
  228.                 }
  229.             }
  230.             break;
  231.               case XK_g:
  232.                 showgrid = !showgrid;
  233.                     break;
  234.               case XK_t:
  235.                         showsurf = !showsurf;
  236.             break;
  237.               case XK_f:
  238.             smooth = !smooth;
  239.             if (smooth) {
  240.                 glShadeModel( GL_SMOOTH );
  241.             } else {
  242.                 glShadeModel( GL_FLAT );
  243.             }
  244.             break;
  245.               case XK_S:
  246.             scale += 0.1;
  247.             printf( "scale: %8.4f\n", scale);
  248.             break;
  249.               case XK_s:
  250.             scale -= 0.1;
  251.             printf( "scale: %8.4f\n", scale);
  252.             break;
  253.               case XK_B:
  254.             bias += 0.0001;
  255.             printf( "bias:  %8.4f\n", bias);
  256.             break;
  257.               case XK_b:
  258.             bias -= 0.0001;
  259.             printf( "bias:  %8.4f\n", bias);
  260.             break;
  261.               case XK_u:
  262.             usegments = (usegments < 2 ? 1 : usegments-1);
  263.             createlists();
  264.             break;
  265.               case XK_U:
  266.             usegments++;
  267.             createlists();
  268.             break;
  269.               case XK_v:
  270.             vsegments = (vsegments < 2 ? 1 : vsegments-1);
  271.             createlists();
  272.             break;
  273.               case XK_V:
  274.             vsegments++;
  275.             createlists();
  276.             break;
  277.               case XK_Escape:
  278.             exit(0);
  279.             break;
  280.             }
  281.             if (!XPending(dpy)) redraw();
  282.         }
  283.         break;
  284.           case Expose:
  285.         XGetGeometry(dpy, window, &root, &x, &y, &w, &h, &bw, &depth);
  286.         winwidth = w;
  287.         winheight = h;
  288.         size = (winwidth < winheight ? winwidth : winheight);
  289.         glViewport((winwidth-size)/2, (winheight-size)/2, size, size);
  290.         redraw();
  291.         break;
  292.           case ConfigureNotify:
  293.         winwidth = event.xconfigure.width;
  294.         winheight = event.xconfigure.height;
  295.         size = (winwidth < winheight ? winwidth : winheight);
  296.         glViewport((winwidth-size)/2, (winheight-size)/2, size, size);
  297.         redraw();
  298.         break;
  299.           case ButtonPress:
  300.         curx = startx = bev->x;
  301.         cury = starty = bev->y;
  302.         spindx = 0;
  303.         spindy = 0;
  304.         tracking = True;
  305.         break;
  306.           case ButtonRelease:
  307.         /*
  308.          * If user released the button while moving the mouse, keep
  309.          * spinning.
  310.          */
  311.         if (bev->x != curx || bev->y != cury) {
  312.             spindx = bev->x - curx;
  313.             spindy = bev->y - cury;
  314.         }
  315.         tracking = False;
  316.         break;
  317.           case MotionNotify:
  318.         if (XPending(dpy)) break;
  319.         curx = bev->x;
  320.         cury = bev->y;
  321.         if (curx != startx || cury != starty) {
  322.             redraw();
  323.             startx = curx;
  324.             starty = cury;
  325.         }
  326.         break;
  327.         }
  328.     } else {
  329.         if (!tracking && (spindx!=0 || spindy!=0)) {
  330.         redraw();
  331.         }
  332.     }
  333.     }
  334. }
  335.  
  336. void gridmaterials(void)
  337. {
  338.     static float front_mat_diffuse[] = { 1.0, 1.0, 0.4, 1.0 };
  339.     static float front_mat_ambient[] = { 0.1, 0.1, 0.1, 1.0 };
  340.     static float back_mat_diffuse[] = { 1.0, 0.0, 0.0, 1.0 };
  341.     static float back_mat_ambient[] = { 0.1, 0.1, 0.1, 1.0 };
  342.  
  343.     glMaterialfv(GL_FRONT, GL_DIFFUSE, front_mat_diffuse);
  344.     glMaterialfv(GL_FRONT, GL_AMBIENT, front_mat_ambient);
  345.     glMaterialfv(GL_BACK, GL_DIFFUSE, back_mat_diffuse);
  346.     glMaterialfv(GL_BACK, GL_AMBIENT, back_mat_ambient);
  347. }
  348.  
  349. void surfacematerials(void)
  350. {
  351.     static float front_mat_diffuse[] = { 0.2, 0.7, 0.4, 1.0 };
  352.     static float front_mat_ambient[] = { 0.1, 0.1, 0.1, 1.0 };
  353.     static float back_mat_diffuse[] = { 1.0, 1.0, 0.2, 1.0 };
  354.     static float back_mat_ambient[] = { 0.1, 0.1, 0.1, 1.0 };
  355.  
  356.     glMaterialfv(GL_FRONT, GL_DIFFUSE, front_mat_diffuse);
  357.     glMaterialfv(GL_FRONT, GL_AMBIENT, front_mat_ambient);
  358.     glMaterialfv(GL_BACK, GL_DIFFUSE, back_mat_diffuse);
  359.     glMaterialfv(GL_BACK, GL_AMBIENT, back_mat_ambient);
  360. }
  361.  
  362. void init(void)
  363. {
  364.     int i;
  365.     static float ambient[] = { 0.0, 0.0, 0.0, 1.0 };
  366.     static float diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
  367.     static float position[] = { 90.0, 90.0, -150.0, 0.0 };
  368.     static float lmodel_ambient[] = { 1.0, 1.0, 1.0, 1.0 };
  369.     static float lmodel_twoside[] = { GL_TRUE };
  370.  
  371.     glMatrixMode(GL_PROJECTION);
  372.     glLoadIdentity();
  373.     gluPerspective( 40.0, 1.0, 2.0, 200.0 );
  374.     glMatrixMode(GL_MODELVIEW);
  375.     glLoadIdentity();
  376.     glGetFloatv(GL_MODELVIEW_MATRIX, modelmatrix);
  377.  
  378.     glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
  379.     glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
  380.     glLightfv(GL_LIGHT0, GL_POSITION, position);
  381.     glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
  382.  
  383.     glEnable(GL_LIGHTING);
  384.     glEnable(GL_LIGHT0);
  385.     glEnable(GL_DEPTH_TEST);
  386.     glEnable(GL_AUTO_NORMAL);
  387.     glEnable(GL_POLYGON_OFFSET_EXT);
  388.     glFrontFace(GL_CCW);
  389.  
  390.     glEnable( GL_MAP2_VERTEX_4 );
  391.     glClearColor(0.25, 0.25, 0.5, 0.0);
  392.  
  393.     glPolygonOffsetEXT( scale, bias );
  394.  
  395.     nobj = gluNewNurbsRenderer();
  396.     gluNurbsProperty(nobj, GLU_SAMPLING_METHOD, GLU_DOMAIN_DISTANCE );
  397.  
  398.     surflist = glGenLists(1);
  399.     gridlist = glGenLists(1);
  400.     createlists();
  401. }
  402.  
  403. void drawmesh(void)
  404. {
  405.     int i, j;
  406.     float *p;
  407.  
  408.     int up2p = 4;
  409.     int uorder = 3, vorder = 3;
  410.     int nu = 4, nv = 4;
  411.     int vp2p = up2p * uorder * nu;
  412.  
  413.     for (j=0; j < nv; j++) {
  414.     for (i=0; i < nu; i++) {
  415.         p = torusbezierpts + (j * vp2p * vorder) + (i * up2p * uorder);
  416.         glPolygonOffsetEXT( scale, bias );
  417.         glMap2f( GL_MAP2_VERTEX_4, 0.0, 1.0, up2p, 3, 0.0, 1.0, vp2p, 3,
  418.              (void*)p );
  419.         if (showsurf) {
  420.         surfacematerials();
  421.         glEvalMesh2( GL_FILL, 0, usegments, 0, vsegments );
  422.         }
  423.         if (showgrid) {
  424.                 gridmaterials();
  425.             glEvalMesh2( GL_LINE, 0, usegments, 0, vsegments );
  426.             }
  427.     }
  428.     }
  429. }
  430.  
  431. void redraw(void)
  432. {
  433.     static int i=0;
  434.     int dx, dy;
  435.     float v[3], n[3], rot[3];
  436.     float len, rlen, ang;
  437.     static GLuint vcount;
  438.  
  439.     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  440.     glColor3f( 1, 0, 0);
  441.  
  442.     if (tracking) {
  443.     dx = curx - startx;
  444.     dy = cury - starty;
  445.     } else {
  446.     dx = spindx;
  447.     dy = spindy;
  448.     }
  449.     if (dx || dy) {
  450.     dy = -dy;
  451.     v[0] = dx;
  452.     v[1] = dy;
  453.     v[2] = 0;
  454.  
  455.     len = length(v);
  456.     ang = -len / 600 * 360;
  457.     norm( v );
  458.     cross( v, z_axis, rot );
  459.  
  460.     /*
  461.     ** This is certainly not recommended for programs that care
  462.     ** about performance or numerical stability: we concatenate
  463.     ** the rotation onto the current modelview matrix and read the
  464.     ** matrix back, thus saving ourselves from writing our own
  465.     ** matrix manipulation routines.
  466.     */
  467.     glLoadIdentity();
  468.     glRotatef(ang, rot[0], rot[1], rot[2]);
  469.     glMultMatrixf(modelmatrix);
  470.     glGetFloatv(GL_MODELVIEW_MATRIX, modelmatrix);
  471.     }
  472.     glLoadIdentity();
  473.     glTranslatef( 0.0, 0.0, -10.0 );
  474.     glMultMatrixf(modelmatrix);
  475.     
  476.     if (useglunurbs) {
  477.     if (showsurf) glCallList(surflist);
  478.     if (showgrid) glCallList(gridlist);
  479.     } else {
  480.     glMapGrid2f( usegments, 0.0, 1.0, vsegments, 0.0, 1.0 );
  481.     drawmesh();
  482.     }
  483.  
  484.     glXSwapBuffers(dpy, window);
  485. }
  486.  
  487. static int attributes[] = {
  488.     GLX_SAMPLES_SGIS, 4,
  489.     GLX_RGBA,
  490.     GLX_DOUBLEBUFFER,
  491.     GLX_RED_SIZE, 1,
  492.     GLX_GREEN_SIZE, 1,
  493.     GLX_BLUE_SIZE, 1,
  494.     GLX_DEPTH_SIZE, 1,
  495.     None,
  496. };
  497.  
  498. static void usage(void)
  499. {
  500.     printf("usage: surfgrid [-f]\n");
  501.     exit(-1);
  502. }
  503.  
  504. Window createwindow( int defW, int defH, int defX, int defY,
  505.              int attributes[], int argc, char **argv,
  506.              Bool fullscreen );
  507.  
  508. static GLboolean queryExtension(char *extName)
  509. {
  510.     /*
  511.     ** Search for extName in the extensions string.  Use of strstr()
  512.     ** is not sufficient because extension names can be prefixes of
  513.     ** other extension names.  Could use strtok() but the constant
  514.     ** string returned by glGetString can be in read-only memory.
  515.     */
  516.     char *p = (char *) glGetString(GL_EXTENSIONS);
  517.     char *end = p + strlen(p);
  518.     while (p < end) {
  519.     int n = strcspn(p, " ");
  520.     if ((strlen(extName) == n) && (strncmp(extName, p, n) == 0)) {
  521.         return GL_TRUE;
  522.     }
  523.     p += (n + 1);
  524.     }
  525.     return GL_FALSE;
  526. }
  527.  
  528. int main(int argc, char **argv)
  529. {
  530.     int i, ms;
  531.  
  532.     for (i=1; i<argc; i++) {
  533.     if (argv[i][0] == '-') {
  534.         switch (argv[i][1]) {
  535.           case 'f':
  536.         fullscreen = 1;
  537.         break;
  538.           default:
  539.         usage();
  540.         break;
  541.         }
  542.     } else {
  543.         usage();
  544.     }
  545.     }
  546.  
  547.     window = createwindow( winwidth, winheight, 50, 50, attributes,
  548.                argc, argv, fullscreen );
  549.     cx = glXCreateContext(dpy, vi, 0, GL_TRUE);
  550.     if (!glXMakeCurrent(dpy, window, cx)) {
  551.     fprintf(stderr, "Can't make window current to context\n");
  552.     return -1;
  553.     }
  554.     if (!queryExtension("GL_EXT_polygon_offset")) {
  555.     printf("Warning: GL_EXT_polygon_offset not supported on this machine.. trying anyway\n");
  556.     }
  557.     init();
  558.     eventloop();
  559.     glXMakeCurrent(dpy, None, NULL);
  560.     glXDestroyContext(dpy, cx);
  561.     XCloseDisplay(dpy);
  562. }
  563.  
  564. /****************************************************************************/
  565.  
  566. float circleknots[] = { 0.0, 0.0, 0.0, 0.25, 0.50, 0.50, 0.75, 1.0, 1.0, 1.0 };
  567.  
  568. void createlists(void)
  569. {
  570.     gluNurbsProperty(nobj, GLU_U_STEP, (usegments-1)*4 );
  571.     gluNurbsProperty(nobj, GLU_V_STEP, (vsegments-1)*4 );
  572.  
  573.     gluNurbsProperty(nobj, GLU_DISPLAY_MODE, GLU_FILL);
  574.     glNewList(surflist, GL_COMPILE);
  575.         surfacematerials();
  576.         gluBeginSurface(nobj);
  577.         gluNurbsSurface(nobj, 10, circleknots, 10, circleknots,
  578.                 4, 28, torusnurbpts, 3, 3, GL_MAP2_VERTEX_4);
  579.         gluEndSurface(nobj);
  580.     glEndList();
  581.  
  582.     gluNurbsProperty(nobj, GLU_DISPLAY_MODE, GLU_OUTLINE_POLYGON);
  583.     glNewList(gridlist, GL_COMPILE);
  584.         gridmaterials();
  585.         gluBeginSurface(nobj);
  586.         gluNurbsSurface(nobj, 10, circleknots, 10, circleknots,
  587.                 4, 28, torusnurbpts, 3, 3, GL_MAP2_VERTEX_4);
  588.         gluEndSurface(nobj);
  589.     glEndList();
  590. }
  591.  
  592. /****************************************************************************/
  593.  
  594. /*
  595.  * Create an X window.
  596.  */
  597.  
  598. static Bool WaitForMapNotify(Display *d, XEvent *e, char *arg)
  599. {
  600.     if ((e->type == MapNotify) && (e->xmap.window == (Window)arg)) {
  601.     return GL_TRUE;
  602.     }
  603.     return GL_FALSE;
  604. }
  605.  
  606. Window createwindow(int w, int h, int x, int y, int attributes[],
  607.             int argc, char **argv, Bool fullscreen)
  608. {
  609.     Window window;
  610.     XSetWindowAttributes swa;
  611.     unsigned int width, height;
  612.     XSizeHints sh;
  613.     XEvent event;
  614.     char buf[20];
  615.  
  616.     dpy = XOpenDisplay(0);
  617.     if (!dpy) {
  618.     fprintf(stderr, "Can't connect to display \"%s\"\n",
  619.         getenv("DISPLAY"));
  620.     exit(1);
  621.     }
  622.     /* tries for a multisample visual first, cause it looks a lot nicer */
  623.     vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributes);
  624.     if (vi) {
  625.     multisampling = 1;
  626.     } else {
  627.     /* try for a non-multisample visual */
  628.     vi = glXChooseVisual(dpy, DefaultScreen(dpy), &attributes[2]);
  629.     if (!vi) {
  630.         fprintf(stderr, "Cannot find visual on \"%s\"\n",
  631.             getenv("DISPLAY"));
  632.         exit(1);
  633.     }
  634.     }
  635.  
  636.     cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual,
  637.                AllocNone);
  638.     swa.background_pixel = 0;
  639.     swa.border_pixel = 0;
  640.     swa.colormap = cmap;
  641.     swa.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask
  642.       | KeyReleaseMask | ButtonPressMask | ButtonMotionMask
  643.     | ButtonReleaseMask;
  644.  
  645.     if (fullscreen) {
  646.     width = DisplayWidth( dpy, 0 );
  647.     height = DisplayHeight( dpy, 0 );
  648.     sh.x = 0;
  649.     sh.y = 0;
  650.     sprintf( buf, "%dx%d+0+0", DisplayWidth(dpy,0), DisplayHeight(dpy,0));
  651.     } else {
  652.     width = w;
  653.     height = h;
  654.     sh.x = x;
  655.     sh.y = y;
  656.     }
  657.     sh.flags = USPosition | PPosition;
  658.     window = XCreateWindow(dpy, RootWindow(dpy, vi->screen), sh.x, sh.y,
  659.                width, height,
  660.                0, vi->depth, InputOutput, vi->visual,
  661.                CWBorderPixel|CWColormap|CWEventMask|CWBackPixel,
  662.                &swa);
  663.     XSetStandardProperties(dpy, window, argv[0], argv[0],
  664.                None, argv, argc, &sh);
  665.     XSetWMColormapWindows(dpy, window, &window, 1);
  666.     if (fullscreen) {
  667.     /* turn off window decorations */
  668.     Atom hints_atom;
  669.     MotifWmHints hints;
  670.  
  671.     hints_atom = XInternAtom( dpy, "_MOTIF_WM_HINTS", 0 );
  672.     hints.flags = MWM_HINTS_DECORATIONS;
  673.     hints.decorations = 0;
  674.     XChangeProperty( dpy, window, hints_atom, hints_atom, 32,
  675.              PropModeReplace, (unsigned char*)&hints, 5 );
  676.     }
  677.     XMapWindow(dpy, window);
  678.     XIfEvent(dpy, &event, WaitForMapNotify, (char*)window);
  679.     return window;
  680. }
  681.  
  682. /*
  683.  * Control points of the torus in Bezier form.  Can be rendered
  684.  * using OpenGL evaluators.
  685.  */
  686. static GLfloat torusbezierpts[] = {
  687.      4.0, 0.0, 0.0, 4.0, 2.0, 0.0, 1.0, 2.0, 3.0, 0.0, 1.0, 2.0,
  688.          3.0, 0.0, 1.0, 2.0, 4.0, 0.0, 1.0, 2.0, 8.0, 0.0, 0.0, 4.0,
  689.          8.0, 0.0, 0.0, 4.0, 4.0, 0.0,-1.0, 2.0, 3.0, 0.0,-1.0, 2.0,
  690.          3.0, 0.0,-1.0, 2.0, 2.0, 0.0,-1.0, 2.0, 4.0, 0.0, 0.0, 4.0,
  691.          2.0,-2.0, 0.0, 2.0, 1.0,-1.0, 0.5, 1.0, 1.5,-1.5, 0.5, 1.0,
  692.          1.5,-1.5, 0.5, 1.0, 2.0,-2.0, 0.5, 1.0, 4.0,-4.0, 0.0, 2.0,
  693.          4.0,-4.0, 0.0, 2.0, 2.0,-2.0,-0.5, 1.0, 1.5,-1.5,-0.5, 1.0,
  694.          1.5,-1.5,-0.5, 1.0, 1.0,-1.0,-0.5, 1.0, 2.0,-2.0, 0.0, 2.0,
  695.          0.0,-2.0, 0.0, 2.0, 0.0,-1.0, 0.5, 1.0, 0.0,-1.5, 0.5, 1.0,
  696.          0.0,-1.5, 0.5, 1.0, 0.0,-2.0, 0.5, 1.0, 0.0,-4.0, 0.0, 2.0,
  697.          0.0,-4.0, 0.0, 2.0, 0.0,-2.0,-0.5, 1.0, 0.0,-1.5,-0.5, 1.0,
  698.          0.0,-1.5,-0.5, 1.0, 0.0,-1.0,-0.5, 1.0, 0.0,-2.0, 0.0, 2.0,
  699.          0.0,-2.0, 0.0, 2.0, 0.0,-1.0, 0.5, 1.0, 0.0,-1.5, 0.5, 1.0,
  700.          0.0,-1.5, 0.5, 1.0, 0.0,-2.0, 0.5, 1.0, 0.0,-4.0, 0.0, 2.0,
  701.          0.0,-4.0, 0.0, 2.0, 0.0,-2.0,-0.5, 1.0, 0.0,-1.5,-0.5, 1.0,
  702.          0.0,-1.5,-0.5, 1.0, 0.0,-1.0,-0.5, 1.0, 0.0,-2.0, 0.0, 2.0,
  703.         -2.0,-2.0, 0.0, 2.0,-1.0,-1.0, 0.5, 1.0,-1.5,-1.5, 0.5, 1.0,
  704.         -1.5,-1.5, 0.5, 1.0,-2.0,-2.0, 0.5, 1.0,-4.0,-4.0, 0.0, 2.0,
  705.         -4.0,-4.0, 0.0, 2.0,-2.0,-2.0,-0.5, 1.0,-1.5,-1.5,-0.5, 1.0,
  706.         -1.5,-1.5,-0.5, 1.0,-1.0,-1.0,-0.5, 1.0,-2.0,-2.0, 0.0, 2.0,
  707.         -4.0, 0.0, 0.0, 4.0,-2.0, 0.0, 1.0, 2.0,-3.0, 0.0, 1.0, 2.0,
  708.         -3.0, 0.0, 1.0, 2.0,-4.0, 0.0, 1.0, 2.0,-8.0, 0.0, 0.0, 4.0,
  709.         -8.0, 0.0, 0.0, 4.0,-4.0, 0.0,-1.0, 2.0,-3.0, 0.0,-1.0, 2.0,
  710.         -3.0, 0.0,-1.0, 2.0,-2.0, 0.0,-1.0, 2.0,-4.0, 0.0, 0.0, 4.0,
  711.         -4.0, 0.0, 0.0, 4.0,-2.0, 0.0, 1.0, 2.0,-3.0, 0.0, 1.0, 2.0,
  712.         -3.0, 0.0, 1.0, 2.0,-4.0, 0.0, 1.0, 2.0,-8.0, 0.0, 0.0, 4.0,
  713.         -8.0, 0.0, 0.0, 4.0,-4.0, 0.0,-1.0, 2.0,-3.0, 0.0,-1.0, 2.0,
  714.         -3.0, 0.0,-1.0, 2.0,-2.0, 0.0,-1.0, 2.0,-4.0, 0.0, 0.0, 4.0,
  715.         -2.0, 2.0, 0.0, 2.0,-1.0, 1.0, 0.5, 1.0,-1.5, 1.5, 0.5, 1.0,
  716.         -1.5, 1.5, 0.5, 1.0,-2.0, 2.0, 0.5, 1.0,-4.0, 4.0, 0.0, 2.0,
  717.         -4.0, 4.0, 0.0, 2.0,-2.0, 2.0,-0.5, 1.0,-1.5, 1.5,-0.5, 1.0,
  718.         -1.5, 1.5,-0.5, 1.0,-1.0, 1.0,-0.5, 1.0,-2.0, 2.0, 0.0, 2.0,
  719.          0.0, 2.0, 0.0, 2.0, 0.0, 1.0, 0.5, 1.0, 0.0, 1.5, 0.5, 1.0,
  720.          0.0, 1.5, 0.5, 1.0, 0.0, 2.0, 0.5, 1.0, 0.0, 4.0, 0.0, 2.0,
  721.          0.0, 4.0, 0.0, 2.0, 0.0, 2.0,-0.5, 1.0, 0.0, 1.5,-0.5, 1.0,
  722.          0.0, 1.5,-0.5, 1.0, 0.0, 1.0,-0.5, 1.0, 0.0, 2.0, 0.0, 2.0,
  723.          0.0, 2.0, 0.0, 2.0, 0.0, 1.0, 0.5, 1.0, 0.0, 1.5, 0.5, 1.0,
  724.          0.0, 1.5, 0.5, 1.0, 0.0, 2.0, 0.5, 1.0, 0.0, 4.0, 0.0, 2.0,
  725.          0.0, 4.0, 0.0, 2.0, 0.0, 2.0,-0.5, 1.0, 0.0, 1.5,-0.5, 1.0,
  726.          0.0, 1.5,-0.5, 1.0, 0.0, 1.0,-0.5, 1.0, 0.0, 2.0, 0.0, 2.0,
  727.          2.0, 2.0, 0.0, 2.0, 1.0, 1.0, 0.5, 1.0, 1.5, 1.5, 0.5, 1.0,
  728.          1.5, 1.5, 0.5, 1.0, 2.0, 2.0, 0.5, 1.0, 4.0, 4.0, 0.0, 2.0,
  729.          4.0, 4.0, 0.0, 2.0, 2.0, 2.0,-0.5, 1.0, 1.5, 1.5,-0.5, 1.0,
  730.          1.5, 1.5,-0.5, 1.0, 1.0, 1.0,-0.5, 1.0, 2.0, 2.0, 0.0, 2.0,
  731.          4.0, 0.0, 0.0, 4.0, 2.0, 0.0, 1.0, 2.0, 3.0, 0.0, 1.0, 2.0,
  732.          3.0, 0.0, 1.0, 2.0, 4.0, 0.0, 1.0, 2.0, 8.0, 0.0, 0.0, 4.0,
  733.          8.0, 0.0, 0.0, 4.0, 4.0, 0.0,-1.0, 2.0, 3.0, 0.0,-1.0, 2.0,
  734.          3.0, 0.0,-1.0, 2.0, 2.0, 0.0,-1.0, 2.0, 4.0, 0.0, 0.0, 4.0,
  735. };
  736.  
  737. /*
  738.  * Control points of a torus in NURBS form.  Can be rendered using
  739.  * the GLU NURBS routines.
  740.  */
  741. static GLfloat torusnurbpts[] = {
  742.          4.0, 0.0, 0.0, 4.0, 2.0, 0.0, 1.0, 2.0, 4.0, 0.0, 1.0, 2.0,
  743.          8.0, 0.0, 0.0, 4.0, 4.0, 0.0,-1.0, 2.0, 2.0, 0.0,-1.0, 2.0,
  744.          4.0, 0.0, 0.0, 4.0, 2.0,-2.0, 0.0, 2.0, 1.0,-1.0, 0.5, 1.0,
  745.          2.0,-2.0, 0.5, 1.0, 4.0,-4.0, 0.0, 2.0, 2.0,-2.0,-0.5, 1.0,
  746.          1.0,-1.0,-0.5, 1.0, 2.0,-2.0, 0.0, 2.0,-2.0,-2.0, 0.0, 2.0,
  747.         -1.0,-1.0, 0.5, 1.0,-2.0,-2.0, 0.5, 1.0,-4.0,-4.0, 0.0, 2.0,
  748.         -2.0,-2.0,-0.5, 1.0,-1.0,-1.0,-0.5, 1.0,-2.0,-2.0, 0.0, 2.0,
  749.         -4.0, 0.0, 0.0, 4.0,-2.0, 0.0, 1.0, 2.0,-4.0, 0.0, 1.0, 2.0,
  750.         -8.0, 0.0, 0.0, 4.0,-4.0, 0.0,-1.0, 2.0,-2.0, 0.0,-1.0, 2.0,
  751.         -4.0, 0.0, 0.0, 4.0,-2.0, 2.0, 0.0, 2.0,-1.0, 1.0, 0.5, 1.0,
  752.         -2.0, 2.0, 0.5, 1.0,-4.0, 4.0, 0.0, 2.0,-2.0, 2.0,-0.5, 1.0,
  753.         -1.0, 1.0,-0.5, 1.0,-2.0, 2.0, 0.0, 2.0, 2.0, 2.0, 0.0, 2.0,
  754.          1.0, 1.0, 0.5, 1.0, 2.0, 2.0, 0.5, 1.0, 4.0, 4.0, 0.0, 2.0,
  755.          2.0, 2.0,-0.5, 1.0, 1.0, 1.0,-0.5, 1.0, 2.0, 2.0, 0.0, 2.0,
  756.          4.0, 0.0, 0.0, 4.0, 2.0, 0.0, 1.0, 2.0, 4.0, 0.0, 1.0, 2.0,
  757.          8.0, 0.0, 0.0, 4.0, 4.0, 0.0,-1.0, 2.0, 2.0, 0.0,-1.0, 2.0,
  758.          4.0, 0.0, 0.0, 4.0,
  759. };
  760.